//
//  main.cpp
//  ringBuffer
//
//  Created by Артемий Соболев on 29.05.12.
//  Copyright (c) 2012 avriy@me.com. All rights reserved.
//

#include <iostream>
#include <pthread.h>
#include <stdio.h>
#include <mach/mach.h>
#include "sys/syscall.h"
#include <fcntl.h>

pthread_rwlock_t spinlock;

#define BUF_SIZE 16
#define BUF_MASK (BUF_SIZE - 1)


class RingBuffer {
    uint8_t inInx, outInx;
    char buffer[BUF_SIZE];
    volatile bool someoneWriting;
    volatile bool someoneSetting;
    
public:
    
    RingBuffer(){
        someoneWriting = false;
        someoneSetting = false;
    }
    void setString(char *string){
        while (someoneSetting){}
        
        if (!someoneSetting) {
            someoneSetting = true;
            pthread_rwlock_rdlock(&spinlock);
            int size;
            size = strlen(string);
            for (int i = 0; i < size; i++) set(string[i]);
            pthread_rwlock_unlock(&spinlock);
        }
    }
    
    void writeToDisk(){
        
        while (someoneWriting){}
        
        if (!someoneWriting) {
            someoneWriting = true;
            pthread_rwlock_rdlock(&spinlock);
            char *tmp = getAll();
            printf("%s",tmp);
            int fd = open("log.txt", O_RDWR|O_CREAT, 0666);
            write(fd, tmp, strlen(tmp));
            pthread_rwlock_unlock(&spinlock);
            someoneWriting = false;
            
        }
        
    }
    
    char *getAll(){
        char *temp = (char *) malloc(indexDiff()*sizeof(char));
        int i = 0;
        while (!areUFool()) {
            *(temp+i) = get();
            i++;
        }
        return temp;
    }
    
    bool areUFool(){
        if(inInx == outInx) return true;
        else return false;
    }
    
    void setToBeEmpty() {outInx = inInx;}
    
    
    uint8_t indexDiff(){
        if (inInx - outInx>=0) {
            return (inInx - outInx);
        }
        else {
            return ((BUF_SIZE - outInx) + inInx);
        }
    }
    
    
private:
    void set(char value){
        buffer[inInx++] = value;
        inInx &= BUF_MASK;
    }
    char get(){
        char value = buffer[outInx++];
        outInx &= BUF_MASK;
        return value;
    }
};

void *bdish(void *ptr){
    RingBuffer *rb = new RingBuffer();
    char ij[] = "89434";
    sleep(10);  
    rb->setString(ij);
    rb->writeToDisk();
    return NULL;
}


int main(int argc, const char * argv[])
{
    pthread_t thr1, thr2;
    pthread_rwlock_init(&spinlock, 0);
    pthread_create(&thr1, NULL, bdish, NULL);
    pthread_create(&thr2, NULL, bdish, NULL);
    
    pthread_join(thr1, NULL);
    pthread_join(thr2, NULL);
    //printf("%s",jkl);
    pthread_rwlock_destroy(&spinlock);
    return 0;
}

